﻿function setParent(el, newParent)
{
	newParent.appendChild(el);
}

SSVC.Wrap.Dojo.Declare("Container", SSVC.SVG.Shape,
{
	NodeType: "svg",
	Marker: null,

	ActionMode: null,

	SelectedElements: null,
	CurrentObject: null,

	selectionRect: null,

	OnDrawingEnd: null,

	CurrentDrawableElement: null,
	Properties: null,

	Actions:
    {
    	Selecting: +1,
    	Moving: +2,
    	Drawing: +3,
    	None: +4
    },

	AffectedKey:
    {
    	SHIFT: 16,
    	CTRL: 17,
    	ENTER: 13,
    	ALT: 18,
    	ESCAPE: 27,
    	DEL: 46
    },

	constructor: function()
	{
		this.Class = "Container";

		this.ActionMode = this.Actions.None;
		this.SelectedElements = [];
		this.SelectedPoint = null;

		this._createMarker();

		SSVC.Wrap.Dojo.On(this.Node, "mousedown", SSVC.Wrap.Dojo.Partial(this.OnMouseDown, this));
		SSVC.Wrap.Dojo.On(this.Node, "mouseup", SSVC.Wrap.Dojo.Partial(this.OnMouseUp, this));
		SSVC.Wrap.Dojo.On(this.Node, "mousemove", SSVC.Wrap.Dojo.Partial(this.OnMouseMove, this));
		SSVC.Wrap.Dojo.On(this.Node, "keydown", SSVC.Wrap.Dojo.Partial(this.OnKeyDown, this));
	},

	OnMouseDown: function(callElement)
	{
		var x = arguments[1].offsetX === undefined ? arguments[1].layerX : arguments[1].offsetX;
		var y = arguments[1].offsetY === undefined ? arguments[1].layerY : arguments[1].offsetY;

		callElement.SelectedPoint = { x: x, y: y };

		if (callElement.ActionMode === callElement.Actions.Drawing)
		{
			callElement.CurrentObject = new callElement.CurrentDrawableElement();
			callElement.CurrentObject.AddProperties(callElement.Properties);
			callElement.addChild(callElement.CurrentObject);
			callElement.CurrentObject.Draw(callElement.SelectedPoint.x, callElement.SelectedPoint.y, x, y, arguments[1].shiftKey);
			callElement.deselectAll();

			return;
		}
		else
		{
			var selectedElement = callElement._getChildByPoint(callElement.SelectedPoint);

			callElement.ActionMode = callElement.Actions.Moving;

			if (!selectedElement)
			{
				callElement.ActionMode = callElement.Actions.Selecting;

				if (callElement.selectionRect !== null)
					callElement._destroyCurrentGroupSelection();

				callElement.deselectAll();

				callElement._createCurrentGroupSelection();

				callElement.selectionRect = new SSVC.SVG.ActiveElement();
				callElement.addChild(callElement.selectionRect);
				callElement.CurrentObject = callElement.selectionRect;
			}

			if (selectedElement && (arguments[1].ctrlKey || arguments[1].shiftKey))
			{
				callElement.select(selectedElement);
			}
			else
				if (selectedElement)
				{
					callElement.selectOnly(selectedElement);
				}
		}
	},

	OnMouseUp: function(callElement)
	{
		callElement.SelectedPoint = null;
		if (callElement.ActionMode === callElement.Actions.Drawing)
			callElement.CurrentObject.Deselect();
		if (callElement.ActionMode === callElement.Actions.Moving && callElement.SelectedElements.length === 1)
			callElement.selectOnlyCurrent();

		if (callElement.selectionRect !== null && callElement.ActionMode === callElement.Actions.Selecting)
		{
			callElement._setCurrentGroupSelection();
			callElement.ActionMode = callElement.Actions.Moving;
			if (callElement.SelectedElements.length === 0)
			{
				callElement._destroyCurrentGroupSelection();
				return;
			}
			callElement.selectionRect.Cursor = SSVC.Utils.Enums.Cursors.Move;
			callElement.CurrentObject = callElement.selectionRect;
		}
	},

	OnMouseMove: function(callElement)
	{
		var offsetX = arguments[1].offsetX === undefined ? arguments[1].layerX : arguments[1].offsetX;
		var offsetY = arguments[1].offsetY === undefined ? arguments[1].layerY : arguments[1].offsetY;
		var evt = arguments[1];
		if (callElement.SelectedPoint === null) return;

		if (callElement.ActionMode === callElement.Actions.Selecting)
		{
			if (callElement.selectionRect !== null)
			{
				callElement.selectionRect.Draw(callElement.SelectedPoint.x, callElement.SelectedPoint.y, offsetX, offsetY, false);
			}
		}
		else
			if (callElement.ActionMode === callElement.Actions.Moving)
			{
				if (callElement.selectionRect !== null)
				{
					callElement._moveSelectedElements(offsetX, offsetY);
					return;
				}

				callElement.CurrentObject.Move(offsetX, offsetY, arguments[1].shiftKey);

			}
			else
				if (callElement.ActionMode === callElement.Actions.Drawing)
				{
					callElement.CurrentObject.Draw(callElement.SelectedPoint.x, callElement.SelectedPoint.y, offsetX, offsetY, arguments[1].shiftKey);
				}
	},

	OnKeyDown: function(callElement)
	{
		if (arguments[1].keyCode === callElement.AffectedKey.DEL)
			callElement.removeSelected();
	},

	OnStartDrawing: function()
	{ },

	_moveSelectedElements: function(x, y)
	{
		var deltaX = this.SelectedPoint.x - x;
		var deltaY = this.SelectedPoint.y - y;
		var newx = this.selectionRect.X;
		var newy = this.selectionRect.Y;

		newx -= deltaX;
		newy -= deltaY;
		//for (var i in this.SelectedElements)
		//{
		//	this.SelectedElements[i].selectedPoint = this.SelectedPoint;
		//	this.SelectedElements[i].Move(deltaX, deltaY, false);
		//}

		//var matrix = this.Node.createSVGMatrix();
		//matrix = matrix.translate(newx, newy);
		//if (this.selectionRect.Node.transform.baseVal.numberOfItems === 0)
		//{
		//	this.selectionRect.Node.transform.baseVal.createSVGTransformFromMatrix(matrix);
		//	var transformObject = this.Node.createSVGTransform();
		//	this.selectionRect.Node.transform.baseVal.appendItem(transformObject);
		//}
		//else
		//	this.selectionRect.Node.transform.baseVal.getItem(0).setMatrix(matrix);
	},

	_getChildByPoint: function(point)
	{
		for (var i in this.Childs)
		{
			var startX = this.Childs[i].Node.getBBox().x;
			var startY = this.Childs[i].Node.getBBox().y;
			var endX = startX + this.Childs[i].Node.getBBox().width;
			var endY = startY + this.Childs[i].Node.getBBox().height;
			if ((point.x >= startX && point.x <= endX) && (point.y >= startY && point.y <= endY)) return this.Childs[i];
		}

		return null;
	},

	_selectChildsByPoint: function(point)
	{
		for (var i in this.Childs)
		{
			var startX = this.Childs[i].Node.getBBox().x;
			var startY = this.Childs[i].Node.getBBox().y;
			var endX = startX + this.Childs[i].Node.getBBox().width;
			var endY = startY + this.Childs[i].Node.getBBox().height;
			if ((startX > point.x && point.x + point.width > endX) && (startY > point.y && point.y + point.height > endY))
				this.select(this.Childs[i]);
		}
	},

	_createCurrentGroupSelection: function()
	{
		this.selectionRect = new SSVC.SVG.ActiveElement();
		this.selectionRect.AddProperties({ strokeWidth: 0, lineColor: "transparent", strokeDash: "none" });
		this.ActionMode = this.Actions.Selection;
		this.addChild(this.selectionRect);
	},

	_setCurrentGroupSelection: function()
	{
		this._selectChildsByPoint(this.selectionRect.Node.getBBox());
		for (var i in this.SelectedElements)
		{
			this.selectionRect.Node.appendChild(this.SelectedElements[i].Node);
		}
	},

	_destroyCurrentGroupSelection: function()
	{
		for (var i in this.SelectedElements)
		{
			this.Node.appendChild(this.SelectedElements[i].Node);
		}
		this.SelectedElements = [];
		try
		{
			this.Node.removeChild(this.selectionRect.Node);
		}
		catch (e)
		{
			console.log(e.description);
		}
		this.selectionRect = null;
	},

	_createMarker: function()
	{
		this.Marker = new SSVC.SVG.Marker("Triangle", "M 0 0 L 20 10 L 0 20 z");
		this.Marker.update(0, 10, 8, 6);

		this.Node.appendChild(this.Marker.defs);
	},

	selectAll: function()
	{
		this.SelectedElements = [];

		for (var i in this.Childs)
		{
			this.SelectedElements.push(this.Childs[i]);
			this.Childs[i].Select();
		}
	},

	selectOnly: function(element)
	{
		for (var i in this.SelectedElements)
		{
			this.deselect(i);
		}

		this.SelectedElements = [];

		this.select(element);
	},

	selectOnlyCurrent: function()
	{
		this.SelectedElements = [];
		for (var i in this.Childs)
		{
			if (this.CurrentObject.ID === this.Childs[i].ID)
			{
				this.select(this.Childs[i]);
				continue;
			}
			this.Childs[i].Deselect();
		}
	},

	select: function(element)
	{
		element.Select();
		this.CurrentObject = element;
		this.SelectedElements.push(element);
	},

	deselect: function(index)
	{
		this.SelectedElements[index].Deselect();
		this.SelectedElements.splice(index, 1);
	},

	deselectAll: function()
	{
		for (var i = 0; i < this.SelectedElements.length; i++)
		{
			this.SelectedElements[i].Deselect();
		}
		this.SelectedElements = [];
	},

	removeSelected: function()
	{
		for (var i in this.SelectedElements)
		{
			this.deselect(i);
			this.remove(this.SelectedElements[i]);
		}
	},

	remove: function(element)
	{
		for (var j in this.Childs)
		{
			if (this.Childs[j].ID === element.ID)
			{
				this.Childs[j].Delete();
				this.Childs.splice(j, 1);
			}
		}
	},

	getSelected: function()
	{
		for (var i in this.Childs)
		{
			if (this.Childs[i].SelectMode === SSVC.SVG.ActiveElement.Enums.SelectMode.Selected)
				this.SelectedElements.push(this.Childs[i]);
		}
	},

	Scale: function(factorX, factorY)
	{
		for (var i = 0; i < this.Childs.length; i++)
		{
			if (factorX !== 1)
				this.Childs[i].ScaleX(factorX);

			if (factorY !== 1)
				this.Childs[i].ScaleY(factorY);
		}
	},

	GetOuterXml: function()
	{
		return this.getXml();
	},

	/// params: SSVC.SVG.ActiveElement
	StartDrawing: function(drawableElement, drawingProperties)
	{
		this.ActionMode = this.Actions.Drawing;
		this.CurrentDrawableElement = drawableElement;
		this.Properties = drawingProperties;
	},

	/// params: SSVC.SVG.ActiveElement
	StartMoving: function(movableElement)
	{
		this.getSelected();
		this.ActionMode = this.Actions.Moving;
	},

	DestroyActions: function()
	{
		this.CurrentObject = null;
		this.ActionMode = this.Actions.None;
	},

	GetXml: function(element)
	{
		if (!element || element === null) element = this;

		var outerXml = element.GetOuterXml();

		var childsXml = "";
		for (var i = 0; i < this.Childs.length; i++)
		{
			try
			{
				var childNode = element.Childs[i].GetOuterXml();
				outerXml.appendChild(childNode);
			}
			catch (e)
			{
				console.error(e.message);
				continue;
			}
		}
		return outerXml;
	},

	ApplyXml: function(xmlstr)
	{
		var xml = SSVC.Wrap.Dojo.Xml.parse(xmlstr);
		this.applyXml(xml.documentElement);
		for (var i = 0; i < xml.documentElement.childNodes.length; i++)
		{
			var child = SSVC.SVG.ActiveElement.XmlDeserialize(xml.documentElement.childNodes[i]);
			this.addChild(child);
		}

		this.deselectAll();
	},

	removeChilds: function()
	{
		for (var j in this.Childs)
		{
			this.Childs[j].Delete();
			this.Childs.splice(j, 1);
		}
		this.Childs = [];
	}
});

SSVC.Wrap.Dojo.SetObject("SSVC.SVG.Container", Container);
